package com.topscomm.mpm.xxlJob;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.convert.Convert;
import com.topscomm.basic.BasicEntity;
import com.topscomm.basic.util.SQLAdapter;
import com.topscomm.mpm.MpmSystemConst;
import com.topscomm.mpm.pojo.MpmProjectEntity;
import com.topscomm.mpm.pojo.MpmProjectMilepostEntity;
import com.topscomm.mpm.pojo.MpmProjectOverdueRecordEntity;
import com.topscomm.mpm.pojo.MpmProjectTaskEntity;
import com.topscomm.mpm.service.impl.MpmProjectMilepostService;
import com.topscomm.mpm.service.impl.MpmProjectOverdueRecordService;
import com.topscomm.mpm.service.impl.MpmProjectService;
import com.topscomm.mpm.service.impl.MpmProjectTaskService;
import com.topscomm.pub.util.ConvertUtil;
import com.topscomm.pub.util.StringBufferProxy;
import com.xxl.job.core.biz.model.ReturnT;
import com.xxl.job.core.handler.IJobHandler;
import com.xxl.job.core.handler.annotation.JobHandler;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.*;
import java.util.stream.Collector;
import java.util.stream.Collectors;

/**
 * @author houyuhang
 * @date 2021/04/21
 * @description: 1、获取项目/里程碑及任务/任务这一时刻的超期信息，如果获取的超期没有在表中记录，则记录超期内容
 * 2、如果在表中记录的超期内容没有获取到，说明已经不再超期，为此条记录赋值超期结束时间
 * @modify:
 */
@JobHandler(value = "overDueRecordJob")
@Component
public class OverDueRecordJob extends IJobHandler {
    private static final Logger log = LoggerFactory.getLogger(BacklogRemind.class);
    @Autowired
    MpmProjectOverdueRecordService mpmProjectOverdueRecordService;
    @Autowired
    MpmProjectService mpmProjectService;
    @Autowired
    MpmProjectMilepostService mpmProjectMilepostService;
    @Autowired
    MpmProjectTaskService mpmProjectTaskService;

    @Override
    public ReturnT<String> execute(String param) {
        try {
            this.handleOverdueProject();
            this.handleOverdueMilepost();
            this.handleOverdueTask();
            return ReturnT.SUCCESS;
        } catch (Exception e) {
            log.error("超期记录失败", e);
            return new ReturnT<>(ReturnT.FAIL_CODE, e.getMessage());
        }
    }

    /**
     * @author houyuhang
     * @date 2021/04/21
     * @description: 处理项目超期
     * @modify:
     */
    public void handleOverdueProject() {
        // 查询项目超期且超期未结束的记录
        StringBufferProxy sql = new StringBufferProxy();
        sql.appendSingle(" {0} = '{1}' and {2} is null ", MpmProjectOverdueRecordEntity.FieldSourcetype,
                MpmSystemConst.OverdueSourcetype.MpmProjectOverdue, MpmProjectOverdueRecordEntity.FieldOverdueenddate);
        List<MpmProjectOverdueRecordEntity> mpmProjectOverdueRecordEntities = mpmProjectOverdueRecordService.queryByWhere(sql.toString());
        Map<String, List<MpmProjectOverdueRecordEntity>> mpmProjectOverdueRecordMap = mpmProjectOverdueRecordEntities.stream()
                .collect(Collectors.groupingBy(item -> ConvertUtil.convertToString(item.getSourceid())));
        // 查询现在超期的项目
        sql.clear();
        sql.appendSingle(" {0} = '{1}' and {2} > {3} ", MpmProjectEntity.FieldProjectstate, MpmSystemConst.ProjectState.ExecuteStateCode,
                SQLAdapter.toChar(SQLAdapter.getDate() + ",'yyyy-mm-dd'"), SQLAdapter.toChar(MpmProjectEntity.FieldPlanenddate + ",'yyyy-mm-dd'"));
        List<MpmProjectEntity> mpmProjectEntities = mpmProjectService.queryByWhere(sql.toString());
        Map<String, List<MpmProjectEntity>> mpmProjectMap = mpmProjectEntities.stream()
                .collect(Collectors.groupingBy(item -> ConvertUtil.convertToString(item.getId())));
        // 循环超期记录，如果已经不再超期，则为超期记录附上当前时间
        List<BasicEntity> updateList = new ArrayList<>();
        for(MpmProjectOverdueRecordEntity mpmProjectOverdueRecordEntity : mpmProjectOverdueRecordEntities) {
            String id = ConvertUtil.convertToString(mpmProjectOverdueRecordEntity.getSourceid());
            if (CollectionUtil.isEmpty(mpmProjectMap.get(id))) {
                mpmProjectOverdueRecordEntity.setOverdueenddate(new Date());
                updateList.add(mpmProjectOverdueRecordEntity);
            }
        }
        mpmProjectOverdueRecordService.updateBatch(updateList);
        // 循环超期项目，如果不存在与超期记录中，则插入超期记录表
        List<BasicEntity> insertList = new ArrayList<>();
        for(MpmProjectEntity mpmProjectEntity : mpmProjectEntities) {
            String id = ConvertUtil.convertToString(mpmProjectEntity.getId());
            if (CollectionUtil.isEmpty(mpmProjectOverdueRecordMap.get(id))) {
                MpmProjectOverdueRecordEntity mpmProjectOverdueRecordEntity = new MpmProjectOverdueRecordEntity();
                mpmProjectOverdueRecordEntity.setProjectcode(mpmProjectEntity.getProjectcode());
                mpmProjectOverdueRecordEntity.setSourcetype(MpmSystemConst.OverdueSourcetype.MpmProjectOverdue);
                mpmProjectOverdueRecordEntity.setSourceid(mpmProjectEntity.getId());
                mpmProjectOverdueRecordEntity.setOverduestartdate(new Date());
                mpmProjectOverdueRecordEntity.setDeptcommoncode(mpmProjectEntity.getDeptcommoncode());
                insertList.add(mpmProjectOverdueRecordEntity);
            }
        }
        mpmProjectOverdueRecordService.insertBatch(insertList);
    }
    /**
     * @author houyuhang
     * @date 2021/04/21
     * @description: 处理里程碑及任务超期，使用里程碑及任务的operatecode作为记录的sourceid
     * @modify:
     */
    public void handleOverdueMilepost() {
        // 查询里程碑及任务超期且超期未结束的记录
        StringBufferProxy sql = new StringBufferProxy();
        sql.appendSingle(" {0} = '{1}' and {2} is null ", MpmProjectOverdueRecordEntity.FieldSourcetype,
                MpmSystemConst.OverdueSourcetype.MpmMilepostOverdue, MpmProjectOverdueRecordEntity.FieldOverdueenddate);
        List<MpmProjectOverdueRecordEntity> mpmProjectOverdueRecordEntities = mpmProjectOverdueRecordService.queryByWhere(sql.toString());
        Map<String, List<MpmProjectOverdueRecordEntity>> mpmProjectOverdueRecordMap = mpmProjectOverdueRecordEntities.stream()
                .collect(Collectors.groupingBy(item -> ConvertUtil.convertToString(item.getSourceid())));
        // 查询现在超期的里程碑及任务
        sql.clear();
        sql.appendSingle(" {0} = '{1}' and {2} > {3} and {4} = '0' and {5}.enabled = 1 ", MpmProjectEntity.FieldProjectstate, MpmSystemConst.ProjectState.ExecuteStateCode,
                SQLAdapter.toChar(SQLAdapter.getDate() + ",'yyyy-mm-dd'"), SQLAdapter.toChar(MpmProjectMilepostEntity.FieldPlanfinishtime + ",'yyyy-mm-dd'"),
                MpmProjectMilepostEntity.FieldMilepoststate, MpmProjectMilepostEntity.tableName);
        Map<String, Object> dataMap = new HashMap<>();
        dataMap.put("whereSql", sql.toString());
        List<Map<String, Object>> mpmProjectMilepostEntities = mpmProjectMilepostService.queryMap(dataMap, "queryOverdueMilepost");
        Map<String, List<Map<String, Object>>> mpmProjectMilepostMap = mpmProjectMilepostEntities.stream()
                .collect(Collectors.groupingBy(item -> ConvertUtil.convertToString(item.get("operatecode"))));
        // 循环超期记录，如果已经不再超期，则为超期记录附上当前时间
        List<BasicEntity> updateList = new ArrayList<>();
        for(MpmProjectOverdueRecordEntity mpmProjectOverdueRecordEntity : mpmProjectOverdueRecordEntities) {
            String id = ConvertUtil.convertToString(mpmProjectOverdueRecordEntity.getSourceid());
            if (CollectionUtil.isEmpty(mpmProjectMilepostMap.get(id))) {
                mpmProjectOverdueRecordEntity.setOverdueenddate(new Date());
                updateList.add(mpmProjectOverdueRecordEntity);
            }
        }
        mpmProjectOverdueRecordService.updateBatch(updateList);
        // 循环超期里程碑及任务，如果不存在与超期记录中，则插入超期记录表
        List<BasicEntity> insertList = new ArrayList<>();
        for(Map<String, Object> mpmProjectMilepostEntity : mpmProjectMilepostEntities) {
            String id = ConvertUtil.convertToString(mpmProjectMilepostEntity.get("operatecode"));
            if (CollectionUtil.isEmpty(mpmProjectOverdueRecordMap.get(id))) {
                MpmProjectOverdueRecordEntity mpmProjectOverdueRecordEntity = new MpmProjectOverdueRecordEntity();
                mpmProjectOverdueRecordEntity.setProjectcode(ConvertUtil.convertToString(mpmProjectMilepostEntity.get("projectcode")));
                mpmProjectOverdueRecordEntity.setSourcetype(MpmSystemConst.OverdueSourcetype.MpmMilepostOverdue);
                mpmProjectOverdueRecordEntity.setSourceid(ConvertUtil.convertToLong(id));
                mpmProjectOverdueRecordEntity.setOverduestartdate(new Date());
                mpmProjectOverdueRecordEntity.setDeptcommoncode(ConvertUtil.convertToString(mpmProjectMilepostEntity.get("deptcommoncode")));
                insertList.add(mpmProjectOverdueRecordEntity);
            }
        }
        mpmProjectOverdueRecordService.insertBatch(insertList);
    }
    /**
     * @author houyuhang
     * @date 2021/04/21
     * @description: 处理任务超期
     * @modify:
     */
    public void handleOverdueTask() {
        // 查询任务超期且超期未结束的记录
        StringBufferProxy sql = new StringBufferProxy();
        sql.appendSingle(" {0} = '{1}' and {2} is null ", MpmProjectOverdueRecordEntity.FieldSourcetype,
                MpmSystemConst.OverdueSourcetype.MpmTaskOverdue, MpmProjectOverdueRecordEntity.FieldOverdueenddate);
        List<MpmProjectOverdueRecordEntity> mpmProjectOverdueRecordEntities = mpmProjectOverdueRecordService.queryByWhere(sql.toString());
        Map<String, List<MpmProjectOverdueRecordEntity>> mpmProjectOverdueRecordMap = mpmProjectOverdueRecordEntities.stream()
                .collect(Collectors.groupingBy(item -> ConvertUtil.convertToString(item.getSourceid())));
        // 查询现在超期的任务
        sql.clear();
        String taskState = "'" + MpmSystemConst.TaskStateCode.TaskNotStartCode + "','" + MpmSystemConst.TaskStateCode.TaskIncompleteCode + "'";
        sql.appendSingle(" {0} = '{1}' and {2} > {3} and {4} in ({5}) and {6}.state = 9 ", MpmProjectEntity.FieldProjectstate, MpmSystemConst.ProjectState.ExecuteStateCode,
                SQLAdapter.toChar(SQLAdapter.getDate() + ",'yyyy-mm-dd'"), SQLAdapter.toChar(MpmProjectTaskEntity.tableName + "." + MpmProjectTaskEntity.FieldPlanenddate + ",'yyyy-mm-dd'"),
                MpmProjectTaskEntity.FieldTaskstate, taskState, MpmProjectTaskEntity.tableName);
        Map<String, Object> dataMap = new HashMap<>();
        dataMap.put("whereSql", sql.toString());
        List<Map<String, Object>> mpmProjectTaskEntities = mpmProjectTaskService.queryMap(dataMap, "queryOverdueTask");
        Map<String, List<Map<String, Object>>> mpmProjectTaskMap = mpmProjectTaskEntities.stream()
                .collect(Collectors.groupingBy(item -> ConvertUtil.convertToString(item.get("id"))));
        // 循环超期记录，如果已经不再超期，则为超期记录附上当前时间
        List<BasicEntity> updateList = new ArrayList<>();
        for(MpmProjectOverdueRecordEntity mpmProjectOverdueRecordEntity : mpmProjectOverdueRecordEntities) {
            String id = ConvertUtil.convertToString(mpmProjectOverdueRecordEntity.getSourceid());
            if (CollectionUtil.isEmpty(mpmProjectTaskMap.get(id))) {
                mpmProjectOverdueRecordEntity.setOverdueenddate(new Date());
                updateList.add(mpmProjectOverdueRecordEntity);
            }
        }
        mpmProjectOverdueRecordService.updateBatch(updateList);
        // 循环超期里程碑及任务，如果不存在与超期记录中，则插入超期记录表
        List<BasicEntity> insertList = new ArrayList<>();
        for(Map<String, Object> mpmProjectTaskEntity : mpmProjectTaskEntities) {
            String id = ConvertUtil.convertToString(mpmProjectTaskEntity.get("id"));
            if (CollectionUtil.isEmpty(mpmProjectOverdueRecordMap.get(id))) {
                MpmProjectOverdueRecordEntity mpmProjectOverdueRecordEntity = new MpmProjectOverdueRecordEntity();
                mpmProjectOverdueRecordEntity.setProjectcode(ConvertUtil.convertToString(mpmProjectTaskEntity.get("projectcode")));
                mpmProjectOverdueRecordEntity.setSourcetype(MpmSystemConst.OverdueSourcetype.MpmTaskOverdue);
                mpmProjectOverdueRecordEntity.setSourceid(ConvertUtil.convertToLong(id));
                mpmProjectOverdueRecordEntity.setOverduestartdate(new Date());
                mpmProjectOverdueRecordEntity.setDeptcommoncode(ConvertUtil.convertToString(mpmProjectTaskEntity.get("deptcommoncode")));
                insertList.add(mpmProjectOverdueRecordEntity);
            }
        }
        mpmProjectOverdueRecordService.insertBatch(insertList);
    }
}
